package com.xfsg.core.log.config;

import com.aliyun.openservices.aliyun.log.producer.ProducerConfig;
import com.aliyun.openservices.aliyun.log.producer.ProjectConfig;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ZhangYi
 * @Classname AliyunLogProperties
 * @Description TODO
 * @Date 2021/12/14 19:49
 */
@Getter
@Setter
@ConfigurationProperties("aliyun.log")
public class AliyunLogProperties {

	private static final String DEFAULT_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";

	private boolean enabled = false;

	private String topic;

	private String source;

	private String timeZone = "Asia/Shanghai";

	private String charset = "UTF-8";

	private String timeFormat = "yyyy-MM-dd HH:mm:ss.SSS";

	private List<String> loggerFilter = new ArrayList<>();

	private String pattern = DEFAULT_PATTERN;

	private AliyunLogProjectConfig project;

	/**
	 * Aliyun Log Producer Config
	 */
	private AliyunProducerConfig producer = new AliyunProducerConfig();

	@Data
	public static class AliyunLogProjectConfig implements Serializable {

		private static final String DEFAULT_STS_TOKEN = "stsToken";

		private static final String DEFAULT_USER_AGENT = "aliyun-log-java-producer";

		private String name;

		private String logstore;

		private String endpoint;

		private String accessKeyId;

		private String accessKeySecret;

		private String stsToken;

		private String userAgent;


		public ProjectConfig buildProjectConfig() {

			return new ProjectConfig(name, endpoint, accessKeyId, accessKeySecret, stsToken, userAgent);
		}

		public ProjectConfig buildProjectConfig(String userAgent) {

			return new ProjectConfig(name, endpoint, accessKeyId, accessKeySecret, stsToken, userAgent);
		}
	}

	@Data
	public static class AliyunProducerConfig implements Serializable {
		private static final long serialVersionUID = -3593242994012311721L;

		/**
		 * 整型 - 字节，默认 100MB，单个 producer 实例能缓存的日志大小上限。
		 */
		private int totalSizeInBytes = ProducerConfig.DEFAULT_TOTAL_SIZE_IN_BYTES;

		/**
		 * 整型 - 毫秒，默认 60 秒，如果 producer 可用空间不足，调用者在 send 方法上的最大阻塞时间，默认为 60 秒
		 */
		private long maxBlockMs = ProducerConfig.DEFAULT_MAX_BLOCK_MS;

		/**
		 * 整型 - 默认为可用处理器个数，执行日志发送任务的线程池大小。
		 */
		private int ioThreadCount = ProducerConfig.DEFAULT_IO_THREAD_COUNT;

		/**
		 * 整型 - 默认为 512 KB，最大可设置成 5MB，当一个 ProducerBatch 中缓存的日志大小大于等于 batchSizeThresholdInBytes 时，
		 * 该 batch 将被发送。
		 */
		private int batchSizeThresholdInBytes = ProducerConfig.DEFAULT_BATCH_SIZE_THRESHOLD_IN_BYTES;

		/**
		 * 整型 - 默认为 4096，最大可设置成 40960，当一个 ProducerBatch 中缓存的日志条数大于等于 batchCountThreshold 时，
		 * 该 batch 将被发送。
		 */
		private int batchCountThreshold = ProducerConfig.DEFAULT_BATCH_COUNT_THRESHOLD;

		/**
		 * 整型 - 毫秒，默认 2 秒，一个 ProducerBatch 从创建到可发送的逗留时间，默认为 2 秒，最小可设置成 100 毫秒。
		 */
		private int lingerMs = ProducerConfig.DEFAULT_LINGER_MS;

		/**
		 * 整型 - 默认 10次，如果某个 ProducerBatch 首次发送失败，能够对其重试的次数，默认为 10 次。
		 * 如果 retries 小于等于 0，该 ProducerBatch 首次发送失败后将直接进入失败队列。
		 */
		private int retries = ProducerConfig.DEFAULT_RETRIES;

		/**
		 * 整型，首次重试的退避时间，默认为 100 毫秒。
		 * Producer 采样指数退避算法，第 N 次重试的计划等待时间为: baseRetryBackoffMs * 2^(N-1)。
		 */
		private long baseRetryBackoffMs = ProducerConfig.DEFAULT_BASE_RETRY_BACKOFF_MS;

		/**
		 * 整型，重试的最大退避时间，默认为 50 秒。
		 */
		private long maxRetryBackoffMs = ProducerConfig.DEFAULT_MAX_RETRY_BACKOFF_MS;

		public ProducerConfig buildProducerConfig(){
			ProducerConfig producerConfig = new ProducerConfig();
			producerConfig.setTotalSizeInBytes(totalSizeInBytes);
			producerConfig.setMaxBlockMs(maxBlockMs);
			producerConfig.setIoThreadCount(ioThreadCount);
			producerConfig.setBatchSizeThresholdInBytes(batchSizeThresholdInBytes);
			producerConfig.setBatchCountThreshold(batchCountThreshold);
			producerConfig.setLingerMs(lingerMs);
			producerConfig.setRetries(retries);
			producerConfig.setBaseRetryBackoffMs(baseRetryBackoffMs);
			producerConfig.setMaxRetryBackoffMs(maxRetryBackoffMs);
			return producerConfig;
		}
	}
}
